package com.example.loginproject.view.views

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.animation.AccelerateInterpolator
import androidx.annotation.RequiresApi
import com.example.loginproject.R
import com.example.loginproject.tool.colorToAlphaColor
import com.example.loginproject.tool.degreeToRadian
import com.example.loginproject.tool.dp2px
import com.example.loginproject.tool.getMode
import com.example.loginproject.tool.getSize
import kotlin.math.cos
import kotlin.math.sin

@RequiresApi(Build.VERSION_CODES.O)
class WaterDropView(context:Context, attrs:AttributeSet?) : View(context, attrs){
    private var mDefaultColor = context.getColor(R.color.light_blue)
    private var mWaterColor:Int = 0
    private var mDefaultStrokeColor:Int = context.getColor(R.color.wave_green)
    private var mStrokeColor:Int = mDefaultStrokeColor
    private var mCircleStrokeWidth = context.dp2px(5)
    private var mRadius = context.dp2px(50)
    private var mpath = Path()//保留绘制路径
    private var mBigCircleCx:Float = 0f
    private var mBigCircleCy:Float =0f
    private var mStartX = 0f
    private var mStartY = 0f
    private var mEndX = 0f
    private var mEndY = 0f

    private var mWaveHeight = context.dp2px(50).toFloat()
    private var mFirstStretchPointX = 0f//第一个拉伸点的
    private var mCurrentWaterLineWidth = 0f//当前水位线的宽度
    private var mCurrentWaterLineHeight = 0f//当前水位线的宽度
    private var mAngle = 30f//扇形一半的角度
    set(value) {
        //当角度确定是一定时调用set方法
        field = value
        mCurrentWaterLineWidth = sin(degreeToRadian(value).toFloat())*mRadius*2
        mCurrentWaterLineHeight = height - cos(degreeToRadian(value).toFloat())*mRadius - mCircleStrokeWidth
    }
    private val mCircleStrokeBgPaint:Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            color = colorToAlphaColor(100,mStrokeColor)
            style = Paint.Style.STROKE
            strokeWidth = mCircleStrokeWidth.toFloat()
        }
    }
    private val mBigCirclePaint:Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            color = mWaterColor
            style = Paint.Style.FILL
        }
    }
    private val mSmallWaterPaint:Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            color = mDefaultStrokeColor
            style = Paint.Style.FILL
        }
    }
    private var mSmallWaterCx = 0f
    private var mSmallWaterCy = 0f
    private var mSmallWaterRadius = context.dp2px(10).toFloat()
    //最小半径
    private var mSmallDefaultWaterRadius = context.dp2px(5).toFloat()
    init {
        //解析属性
        context.obtainStyledAttributes(attrs,R.styleable.WaterDropView).apply {
            mWaterColor = getColor(R.styleable.WaterDropView_water_color,mDefaultColor)
            mStrokeColor = getColor(R.styleable.WaterDropView_stroke_color,mDefaultColor)
            recycle()
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var mWidth = 0
        var mHeight = 0
        mWidth = when(getMode(widthMeasureSpec)){
            MeasureSpec.EXACTLY -> getSize(widthMeasureSpec)
            else -> 2*mRadius
        }
        mHeight = when(getMode(heightMeasureSpec)){
            MeasureSpec.EXACTLY -> getSize(heightMeasureSpec)
            else -> 3*mRadius
        }
        setMeasuredDimension(mWidth,mHeight)
    }
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if(2*mRadius==width&&3*mRadius==height){
            //尺寸是外部精确的，需要再次确定R的值
            mRadius = width/2
            if(mRadius>height/3){
                mRadius = height/3
            }
        }
        //半径需要减去边缘线的宽度
        mRadius -= mCircleStrokeWidth/2
        //确定圆心
        mBigCircleCx = width.toFloat()/2
        mBigCircleCy = height - mRadius.toFloat() - mCircleStrokeWidth

        mSmallWaterCx = width.toFloat()/2
        mSmallWaterCy = mSmallDefaultWaterRadius
        mSmallWaterRadius = mSmallDefaultWaterRadius
        mAngle = 45f
    }

    override fun onDraw(canvas: Canvas) {
        drawCircleStroke(canvas)
        drawSmallWater(canvas)
        drawBigWater(canvas)
    }
    private fun drawCircleStroke(canvas: Canvas?){
        canvas?.drawCircle(mBigCircleCx,mBigCircleCy,mRadius.toFloat(),mCircleStrokeBgPaint)
    }

    private fun drawSmallWater(canvas: Canvas?){
        canvas?.drawCircle(mSmallWaterCx,mSmallWaterCy,mSmallWaterRadius,mSmallWaterPaint)
    }
    private fun drawBigWater(canvas: Canvas?){
        //起点坐标
        val degree = degreeToRadian(mAngle)
        mStartX = mRadius*(1+ sin(degree)).toFloat()//
        mStartY = height - mCircleStrokeWidth -mRadius*(1- cos(degree).toFloat())
        //终点坐标
        mEndX =  mRadius*(1- sin(degree)).toFloat()//
        mEndY = mStartY
        //如果角度为0，结束
        if(mAngle == 0f) return
        mpath.reset()//清一下mPath
        mpath.moveTo(mStartX,mStartY)
        mpath.addArc(mBigCircleCx-mRadius,mBigCircleCy-mRadius,
            mBigCircleCx+mRadius,mBigCircleCy+mRadius,
            90-mAngle,//起始角度
        2*mAngle//扇形扫过的角度
        )
        mpath.cubicTo(
            mFirstStretchPointX,mStartY-mWaveHeight,
            mFirstStretchPointX+sin(degree.toFloat())*mRadius,mStartY+mWaveHeight,
            mStartX,mStartY)
       mpath.close()
        canvas?.drawPath(mpath,mBigCirclePaint)
    }
    private var mWaveAnimation:ValueAnimator? = null
    private fun startWaterWaveAnimation(){
        if(visibility == VISIBLE){
            ValueAnimator.ofFloat(0f,mRadius.toFloat()).apply {
                duration = 500
                repeatCount = ValueAnimator.INFINITE
                repeatMode = ValueAnimator.REVERSE
                addUpdateListener {
                    mFirstStretchPointX = it.animatedValue as Float
                    invalidate()
                }
                start()
                mWaveAnimation = this
            }
        }
    }
    //角度发生变化
    private var mDegreeAnimation:ValueAnimator? = null
    private fun startDegreeAnimation(){
        ValueAnimator.ofFloat(0f,180f).apply {
            duration = 1000
            addUpdateListener {
                mAngle = it.animatedValue as Float
                invalidate()
            }
            start()
            mDegreeAnimation = this
        }
    }
    private var isFirst = true
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if(event?.action== MotionEvent.ACTION_DOWN){

            if(isFirst){
                dropDownAndScaleAnimation()
                startWaterWaveAnimation()
            }else{
                stopAnimation()
            }
            isFirst = !isFirst
        }
        return true
    }

    private fun stopAnimation() {
        mDegreeAnimation?.cancel()
        mWaveAnimation?.cancel()
        mDropDownAnimation?.cancel()
    }

    //掉落放大动画
    private var mDropDownAnimation:ValueAnimator? = null
    private fun dropDownAndScaleAnimation(){
        ValueAnimator.ofFloat(
           mSmallDefaultWaterRadius, height-mCircleStrokeWidth-2*mSmallDefaultWaterRadius).apply {
                duration = 1000
            interpolator = AccelerateInterpolator()//加速
            repeatCount = ValueAnimator.INFINITE
           repeatMode = ValueAnimator.RESTART
            addUpdateListener {
                mSmallWaterCy = it.animatedValue as Float
                if(mSmallWaterCy > mCurrentWaterLineHeight){
                   // this@WaterDropView.visibility = INVISIBLE
                    mAngle+=5
                    if(mAngle == 180f){
                        mDropDownAnimation?.cancel()
                    }else{
                        mDropDownAnimation?.start()
                    }
                }
                invalidate()
            }
            start()
            mDropDownAnimation = this
        }
    }

    override fun onWindowVisibilityChanged(visibility: Int) {
        if(visibility == INVISIBLE){
            stopAnimation()
        }
    }
}
